package org.batatasframework.support.searchable;

import org.batatasframework.support.event.SearchableRequest;

/**
 * <pre>
 * 这里负责自定义查询、统计等的管理类，包括解析数据库表、解析定义文件等
 * 
 * 方式一：给定一个表名，解析出所有可以用于查询和显示的字段
 * 
 * 到底这里要不要管数据库连接的问题，如果不管，则每次都需要传进来，如果管，则如何与外面的调用共用同一个连接？
 * </pre>
 * @author jackson
 *
 */
public interface SearchablePlatform{
	
	/**
	 * <pre>
	 * 代码级别的处理。
	 * 
	 * 步骤一：
	 * 调用这个方法需要传入一个查询参数的配置信息的对象：{@link SearchableRequest}
	 * 可以设置处理器执行时需要的一些参数信息，详细情况参考：{@link SearchableRequest "SearchableConfig说明"}
	 * 
	 * 步骤二：
	 * 设置返回字段，表关联，查询条件等
	 * 
	 * 步骤三：
	 * 处理器(参考：{@link SearchableHandler})对象需要有相应的读取的缓冲区(参考：{@link org.batatasframework.support.database.spi.ResultBuffer ResultBuffer})
	 * 有如下几种缓冲区的读取对象：
	 * 1. {@link org.batatasframework.support.searchable.result.SearchResultBuffer SearchResultBuffer}查询列表
	 * 2. {@link org.batatasframework.support.searchable.result.GroupResultBuffer GroupResultBuffer}查询分组
	 * 3. {@link org.batatasframework.support.searchable.result.StatisticsResultBuffer StatisticsResultBuffer}查询统计
	 * 
	 * 步骤四：
	 * 缓冲区({@link org.batatasframework.support.database.spi.ResultBuffer ResultBuffer})的数据并不是结果数据，结果数据需要由{@link org.batatasframework.support.database.spi.ResultWritable ResultWriter}的子类来实现
	 * 可以把数据写成几种结果：
	 * 1. {@link org.batatasframework.support.searchable.writer.ObjectResultWriter ObjectResultWriter} 普通的对象或可以直接序列化为json格式的对象
	 * 2. {@link org.batatasframework.support.searchable.writer.HtmlResultWriter HtmlResultWriter}生成table的html源代码
	 * 3. {@link org.batatasframework.support.searchable.writer.ExcelResultWriter ExcelResultWriter}把结果写入到excel文件
	 * 4. 继承{@link org.batatasframework.support.database.spi.ResultWritable ResultWriter}接口，实现更多的自定义返回结果集
	 * 
	 * </pre>
	 * <hr/>
	 * 参考代码：
	 * <pre>
	 * 
	 * //1. 创建SearchableConfig对象
	 * SearchableConfigurable searchableConfig = new SearchableConfiguration(...);
	 * 
	 * //2. 生成SearchableHandler对象
	 * SearchableHandler searchableHandler = searchablePlatform.buildSearchableHandler(searchableConfig);
	 * 
	 * //3. 设置查询字段、关联表、查询条件、排序等
	 * searchableHandler.field(...);
	 * searchableHandler.join(...);
	 * searchableHandler.query(...);
	 * searchableHandler.orderBy(...);
	 * 
	 * //4. 创建缓冲区有几种可选
	 *  //   1. {@link org.batatasframework.support.searchable.result.SearchResultBuffer SearchResultBuffer}
	 *  //   2. {@link org.batatasframework.support.searchable.result.GroupResultBuffer GroupResultBuffer}
	 *  //   3. {@link org.batatasframework.support.searchable.result.StatisticsResultBuffer StatisticsResultBuffer}
	 * //SearchResultBuffer searchResultBuffer = new SearchResultBuffer(searchableHandler);
	 *  searchableHandler.execute(searchResultBuffer);
	 * 
	 * //5. 创建需要的结果集
	 * ObjectResultWriter jsonWriter = new ObjectResultWriter(stream);
	 * jsonWriter.flush();//最后特别要注意的是需要调用"flush()"方法把数据写入对象
	 * </pre>
	 */
	SearchableHandler buildSearchableHandler(SearchableRequest searchableConfig) throws Exception;
//	
//	/**
//	 * <pre>
//	 * 创建一个上下文，创建后这个上下文是游离状态的，这个时候可以在代码级的进行一些字段的指定
//	 * 创建完成后，可以注册到管理器，这样下次使用同名来进行引用的时候，如果存在，则不再创建新的上下文
//	 * 
//	 * 也可以不注册，不注册的话使用同一个名字会创建不同的上下文对象
//	 * 
//	 * <font color="red">调用本方法，一定会重新创建一个{@link TableDefinition} 对象</font>
//	 * 
//	 * 一个上下文被创建后需要被保存起来，并且以后在使用的时候是确定的，也就是说只需要创建一次。
//	 * 在请求里可以给上下文指定要查询哪些定义，传递过来了哪些查询条件，如何分组等信息；在执行的时候，由上下文创建一个
//	 * 执行的处理器来处理；整个过程定义完之后，都是自动完成的。
//	 * 
//	 * 这里是手动定义上下文的情况；上下文还可以是通过配置文件定义好的。直接通过"key"来访问取得，参考：{@link #getSearchableContext(String)}
//	 * 手动创建的上下文也可以注册回去，这样在其它地方就可以通过注册的"key"来引用；但无法保存注册和引用的先后顺序。
//	 * </pre>
//	 */
//	TableDefinitionBuilder buildSearchableContextBuilder(String schemaName, String catalogName, String tableName) throws Exception;
//	TableDefinitionBuilder buildSearchableContextBuilder(TableMetadata sourceTableMetadata) throws Exception;

//	TableDefinition getSearchableContext(Object key);
//	
//	/**
//	 * <pre>
//	 * 如果添加成功，则返回null值；如果没有使用强制替换，并且已经存在旧值，则这里返回旧值；
//	 * 如果旧值与被注册的对象是同一个对象的，则认为是注册成功，返回null值。
//	 * </pre>
//	 */
//	TableDefinition registSearchableContext(Object key, TableDefinition context, boolean forcedReplace);
//	
//	/**
//	 * <pre>
//	 * 执行一次查询操作，
//	 * 
//	 * 应该把是否分页，如果分页的话使用的分页情况加进来
//	 * 
//	 * 分页应该支持两种方式，一种是后台进行分页，一种是把所有数据加载到前端，在前端进行分页处理
//	 * 
//	 * 这里包括了统计的处理，因为统计的请求可以通过{@link SearchableRequest}来指定
//	 * </pre>
//	 * @see SearchableRequest
//	 */
//	SearchableHandler buildSearchableHandler(SearchableRequest request, SearchableContext context) throws Exception;
	
	//	
//	/**
//	 * 使用默认的数据库名，具体定义参考{@link #instanceContext(String, String)}
//	 * @param tableName 表名
//	 * @return 查询定义的上下文对象
//	 * @throws Exception
//	 */
//	SearchContext instanceContext(String tableName) throws Exception;
//	
//	DatabaseAccessor buildDatabaseAccessor() throws Exception;
}
